/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2012/07/11
* File: OGLRenderSystem.h
* Blog: http://www.cnblogs.com/zengqh/
**/

#ifndef OGLRenderSystem_h__
#define OGLRenderSystem_h__

#include "../../Core/Core.h"
#include "../../Core/Declare.h"
#include "../RenderSystem.h"
#include "../RenderTarget.h"

class OGLRenderSystem : public RenderSystem
{
public:
	OGLRenderSystem();
	~OGLRenderSystem();

	bool beginScene();
	bool endScene();

	void setTransform(TransformState state, const glm::mat4& transform);
	const glm::mat4& getTransform(TransformState state) const;

	void setViewport(const Recti& view_port);
	const Recti& getViewport() const;

	s32 getType() const;

	void bindBuffer(GLenum target, GLuint buffer);
	void deleteBuffers(GLsizei n, GLuint* buffers);

	void setFVF(FVFState fvf);

	void setGraphicsBuffer(BufferState state, 
		GraphicsBuffer* graphics_buffer);

	void setEffect(Effect* effect);

	void setMaterial(MaterialData* material_data);

	const MaterialData& getMaterial() const;

	void addLight(LightData* light_data);
	const LightData& getLight(int index) const;
	void deleteAllLights();

	void drawPrimitiveIndex(u32 primitive_count, 
		PrimitiveState mode, u32 offset, bool is_index_16);

	Texture* createTexture(const char* path, bool is_mipmap /* = false */);

	GraphicsBuffer* createGraphicsBuffer(
		BufferUsage usage, 
		u32 access_hint, 
		BufferState target, 
		void* init_data = NULL, 
		u32 size = 0);

	void clearColor(const glm::vec4& color);
	void clearZBuffer();

	void addFrameListener(FrameListener* listener);

	void setEffectService(EffectService* es);

	Effect* createEffect();

	void setRenderTarget(RenderTarget* rt);

	RenderTarget* createRTT(const Dimension2Di& size);

protected:
	void applyFVF(bool en);
	void applyMatrix();
	void applyGraphicsBuffer();
	void applyEffect();
	void applyMaterial();

	void applyLight();

	GLint getTextureWrapMode(const u8 clamp);

	bool applyFrameStarted();
	bool applyFrameEnded();

protected:
	glm::mat4			_matrix_list[TS_Count];
	s32					_rs_state;
	Recti				_view_port;
	Recti				_screen_view_port;
	GraphicsBuffer*		_gb_list[BS_COUNT];
	FVFState			_fvf_state;
	GLSLEffect*			_glsl_effect;
	MaterialData*		_material_data;
	MaterialData		_last_material_data;
	bool				_is_reset_material_data;

	typedef				std::vector<LightData*> LightDataList;
	typedef				std::list<FrameListener*> FrameListenerList;
	LightDataList		_light_data_list;
	LightData			_dummy_light;
	u32					_max_light_num;
	FrameListenerList	_frame_listener_list;
	EffectService*		_effect_service;
	RenderTarget*		_render_target;
};

#endif    /* OGLRenderSystem_h__ */